#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include "../vm/c_vm.h"
#include "c_lexer.h"

// Define a jump buffer for recovery after segmentation fault
static jmp_buf segv_buf;

// Signal handler function
static void segv_handler(int signal) {
    printf("SEGV caught: Memory access error during lexical analysis\n");
    longjmp(segv_buf, 1);  // Jump back to setjmp location
}

// Read code from file
char* read_file(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("Error: Cannot open file '%s'\n", filename);
        return NULL;
    }
    
    // Get file size
    fseek(file, 0, SEEK_END);
    long file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    
    // Allocate memory
    char* buffer = (char*)malloc(file_size + 1);
    if (!buffer) {
        printf("Error: Memory allocation failed\n");
        fclose(file);
        return NULL;
    }
    
    // Read file content
    size_t read_size = fread(buffer, 1, file_size, file);
    buffer[read_size] = '\0';
    
    fclose(file);
    return buffer;
}

int main(int argc, char** argv) {
    const char* file_path;
    const char* output_file = "test_lexer.txt";
    FILE* output_fp = NULL;
    printf("Starting test...\n");
    
    // Determine test file path
    if(argc > 1){
         file_path = argv[1];
    }else{
         file_path = "test.c";
    }
    
    // Load test code from file
    printf("Loading test file: %s\n", file_path);
    char* test_code = read_file(file_path);
    
    if (!test_code) {
        printf("Failed to load test file\n");
        return 1;
    }
    
    printf("File loaded successfully\n");
    printf("File content length: %u bytes\n", (unsigned int)strlen(test_code));
    printf("First 50 characters: %.50s...\n", test_code);
    
    // 打开输出文件
    output_fp = fopen(output_file, "w");
    if (!output_fp) {
        printf("Error: Cannot open output file '%s'\n", output_file);
        free(test_code);
        return 1;
    }
    
    // Analyze code
    printf("Starting lexical analysis...\n");
    fprintf(output_fp, "Starting lexical analysis...\n");
    
    // Check if input pointer is valid
    if (!test_code) {
        printf("Error: Cannot analyze NULL code pointer\n");
        fprintf(output_fp, "Error: Cannot analyze NULL code pointer\n");
        fclose(output_fp);
        return 1;
    }
    
    // Set up signal handler to catch segmentation faults
    signal(SIGSEGV, segv_handler);
    
    // Use setjmp to establish recovery point
    LexResult* result = NULL;
    if (setjmp(segv_buf) == 0) {
        // Normal execution path
        // Call lexical analysis function and check return result
        result = analyze_c_code(test_code);
    } else {
        // Recovery path after segmentation fault
        printf("Segmentation fault occurred during analysis, cannot complete the process\n");
        fprintf(output_fp, "Segmentation fault occurred during analysis, cannot complete the process\n");
        result = NULL;
    }
    
    // Check if return result is valid
    if (result) {
        printf("Lexical analysis successful, found %d tokens\n", result->count);
        fprintf(output_fp, "Lexical analysis successful, found %d tokens\n", result->count);
        
        // Get analysis result
        char* result_str = get_result_string(result);
        if (result_str) {
            // 将结果写入文件而不是打印到控制台
            fprintf(output_fp, "%s\n", result_str);
            printf("Results have been written to %s\n", output_file);
            if (result->error_count > 0) {
                char* error_str = get_error_string(result);
                if (error_str) {
                    fprintf(output_fp, "词法分析存在错误：\n%s\n", error_str);
                    printf("Errors have been written to %s\n", output_file);
                    free_result_string(error_str);
                } else {
                    printf("Warning: Failed to get error string\n");
                    fprintf(output_fp, "Warning: Failed to get error string\n");
                }
            }
            free_result_string(result_str);
        }
        // else {
        //     printf("Warning: Failed to get result string\n");
        //     fprintf(output_fp, "Warning: Failed to get result string\n");
            
        //     // 如果get_result_string失败，则尝试单独获取错误信息
        //     if (result->error_count > 0) {
        //         char* error_str = get_error_string(result);
        //         if (error_str) {
        //             fprintf(output_fp, "词法分析存在错误：\n%s\n", error_str);
        //             printf("Errors have been written to %s\n", output_file);
        //             free_result_string(error_str);
        //         } else {
        //             printf("Warning: Failed to get error string\n");
        //             fprintf(output_fp, "Warning: Failed to get error string\n");
        //         }
        //     }
        // }
        
        // Free result
        free_lex_result(result);
    } else {
        printf("Lexical analysis failed: NULL result returned\n");
        fprintf(output_fp, "Lexical analysis failed: NULL result returned\n");
    }
    
    // 关闭输出文件
    fclose(output_fp);
    
    // Free resources
    free(test_code);
    
    printf("Test completed\n");
    return 0;
} 